using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MacomberMap.Common.Database_Interface;
using System.Reflection;
using MacomberMap.Common.Permissions;
using System.Xml;

namespace MacomberMap.Loader.User_Interfaces.UserRoles
{
    /// <summary>
    /// This class provides a view into user roles
    /// </summary>
    public partial class frmUserRoles : Form
    {
        #region Variable declarations
        /// <summary>The master database to which the system is connected</summary>
        public MM_Database DbConnection;

        /// <summary>Our current snapshot of users, roles, and databases</summary>
        public DataSet UsersAndRoles;
        #endregion

        #region Initialization
        /// <summary>
        /// Initilize the user roles form
        /// </summary>        
        /// <param name="DbConnection">The datbase connection</param>
        /// <param name="StartingTab">The tab that should first be activated</param>
        public frmUserRoles(MM_Database DbConnection, int StartingTab)
        {
            InitializeComponent();
            tabs.SelectedIndex = StartingTab;

            //Load our roles, users and databases
            UsersAndRoles = DbConnection.LoadUsersAndRoles();

            //Assign our default tables
            lvRoleList.AssignTable(UsersAndRoles.Tables["Roles"], lvUsersByRole);            
            lvUserList.AssignTable(UsersAndRoles.Tables["Users"], lvRolesByUser);

            //Assign our sub-information tables
            
            lvRolesByUser.AssignTable(UsersAndRoles.Tables["Roles"]);
            lvUsersByRole.AssignTable(UsersAndRoles.Tables["Users"]);
            frmUserRoles_SizeChanged(this, EventArgs.Empty);
        }

        /// <summary>
        /// Update the size of our role form by moving the ok and cancel buttons, and the splitters
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmUserRoles_SizeChanged(object sender, EventArgs e)
        {            
            int Distance = tabs.Left;
            btnCancel.Location = new Point(DisplayRectangle.Width - btnCancel.Width - Distance, DisplayRectangle.Height - btnCancel.Height - Distance);
            btnOK.Location = new Point(btnCancel.Left - btnOK.Width - btnOK.Width, btnCancel.Top);
            tabs.Size = new Size(btnCancel.Right - Distance, btnCancel.Top - Distance-Distance);            
        }
        #endregion


        /// <summary>
        /// This class provides a potentially constrained view into a role, user and/or database
        /// </summary>
        private class MM_TableBasedView : ListView
        {
            #region Variable declarations
            /// <summary>The table upon which this view is based</summary>
            public DataTable BaseTable;

            /// <summary>The role constraint (if any) to be applied to the table.</summary>
            public DataRow ConstrainingRow;

            /// <summary>
            /// The sub-views affected by changes in this item's view
            /// </summary>
            public MM_TableBasedView[] DownstreamViews;
            #endregion

            #region Initialization
            /// <summary>
            /// Auto-setup our table-based view
            /// </summary>
            public MM_TableBasedView()
            {
                this.Dock = DockStyle.Fill;
                this.View = View.Details;
                this.FullRowSelect = true;
            }

            /// <summary>
            /// Initialize the new view for the table
            /// </summary>
            /// <param name="BaseTable">The table upon which the item is based</param>       
            /// <param name="DownstreamViews">The views that are connected to the current one</param>
            public void AssignTable(DataTable BaseTable, params MM_TableBasedView[] DownstreamViews)
            {
                this.BaseTable = BaseTable;
                this.DownstreamViews = DownstreamViews;
                UpdateConstraint(null);
                this.SelectedIndexChanged += new EventHandler(MM_TableBasedView_SelectedIndexChanged);
            }

            //Handle the change in our selected index
            private void MM_TableBasedView_SelectedIndexChanged(object sender, EventArgs e)
            {
                if (DownstreamViews.Length > 0)
                    foreach (MM_TableBasedView DownstreamView in DownstreamViews)
                        if (SelectedItems.Count == 1)
                            DownstreamView.UpdateConstraint(SelectedItems[0].Tag as DataRow);
                        else
                            DownstreamView.UpdateConstraint(null);
            }

            /// <summary>
            /// Update a constraint with a new value
            /// </summary>
            /// <param name="ConstrainingRow">The row constraining the current row</param>
            public void UpdateConstraint(DataRow ConstrainingRow)
            {
                this.ConstrainingRow = ConstrainingRow;

                //Clear our items, and make sure our columns are in place
                this.Items.Clear();
                foreach (DataColumn col in BaseTable.Columns)
                    if (col.ColumnName == "PERMISSIONS")
                    {
                        foreach (FieldInfo fI in typeof(MM_User).GetFields())
                            if (!this.Columns.ContainsKey(fI.Name))
                                this.Columns.Add(fI.Name, fI.Name);
                    }
                    else if (!this.Columns.ContainsKey(col.ColumnName))
                        this.Columns.Add(col.ColumnName, col.ColumnName);

                //If we have no constraints and no sub-detail, we should hide
                if (ConstrainingRow == null && DownstreamViews.Length == 0)
                {
                    this.Visible = false;
                    return;
                }

                //If we have no constraining row, show everything
                else if (ConstrainingRow == null)
                    foreach (DataRow dr in BaseTable.Rows)
                        AddRow(dr);

                //If we're constraining by role, update accordingly
                else if (ConstrainingRow.Table.TableName == "Roles" && BaseTable.TableName == "Users")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if (Convert.ToInt32(dr["USERROLE"]) == Convert.ToUInt32(ConstrainingRow["ROLEID"]))
                            AddRow(dr);
                }
                else if (ConstrainingRow.Table.TableName == "Roles" && BaseTable.TableName == "Databases")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if ((Convert.ToString(dr["DBACCESS"]))[Convert.ToInt32(ConstrainingRow["ROLEID"])] == '1')
                            AddRow(dr);
                }
                else if (ConstrainingRow.Table.TableName == "Users" && BaseTable.TableName == "Roles")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if (Convert.ToInt32(dr["ROLEID"]) == Convert.ToUInt32(ConstrainingRow["USERROLE"]))
                            AddRow(dr);
                }
                else if (ConstrainingRow.Table.TableName == "Users" && BaseTable.TableName == "Databases")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if ((Convert.ToString(dr["DBACCESS"])[Convert.ToInt32(ConstrainingRow["USERROLE"])]) == '1')
                            AddRow(dr);
                }
                else if (ConstrainingRow.Table.TableName == "Databases" && BaseTable.TableName == "Roles")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if ((Convert.ToString(ConstrainingRow["DBACCESS"])[Convert.ToInt32(dr["ROLEID"])]) == '1')
                            AddRow(dr);
                }
                else if (ConstrainingRow.Table.TableName == "Databases" && BaseTable.TableName == "Users")
                {
                    foreach (DataRow dr in BaseTable.Rows)
                        if ((Convert.ToString(ConstrainingRow["DBACCESS"])[Convert.ToInt32(dr["USERROLE"])]) == '1')
                            AddRow(dr);
                }
                this.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
                this.Visible = true;
            }

            /// <summary>
            /// Add a new row to our list view
            /// </summary>
            /// <param name="dr"></param>
            private void AddRow(DataRow dr)
            {
                ListViewItem NewItem = this.Items.Add(Convert.ToString(dr[0]));
                for (int a = 1; a < BaseTable.Columns.Count; a++)
                    if (BaseTable.Columns[a].ColumnName == "PERMISSIONS")
                    {
                        String[] splStr = Convert.ToString(dr[a]).Split(new char[] { ' ', '=', '"' }, StringSplitOptions.RemoveEmptyEntries);
                        for (int b = 1; b < splStr.Length-1; b += 2)
                            NewItem.SubItems.Add(splStr[b + 1]);
                    }
                    else
                        NewItem.SubItems.Add(Convert.ToString(dr[a]));
                NewItem.Tag = dr;
            }


            #endregion
        }       
    }
}